<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #canvas {
        background-color: black;
        height: 800px;
        width: 800px;
      }
    </style>
  </head>
  <body>
    <div id="canvas"></div>
    <script type="module">
      import * as THREE from '../node_modules/three/build/three.module.js';
      import ThreeBase from '../ThreeBase.js';

      import { GLTFLoader } from '../node_modules/three/examples/jsm/loaders/GLTFLoader.js';
      import { circlePointsShader } from '../shaderUtil.js';
      class MyApple extends ThreeBase {
        constructor() {
          super();
          this.initCameraPos = [1, 10, 10];
          this.time = 0;
          this.speed = 0.001;
          this.speed1 = 0.0005;
        }

        animateAction() {
          if (this.mesh) {
            if (this.time >= 0) {
              this.speed += this.speed1;
              this.time += this.speed;
              const positions = this.mesh.geometry.attributes.position;
              const normal = this.mesh.geometry.attributes.normal;
              const initialPositions = this.mesh.geometry.attributes.initialPosition;
              const displacement = this.mesh.geometry.attributes.displacement;
              const count = positions.count;
              let t = 2.0 - this.time;
              for (let i = 0; i < count; i++) {
                const d = displacement.getX(i) * t;
                const ix = initialPositions.getX(i);
                const iy = initialPositions.getY(i);
                const iz = initialPositions.getZ(i);
                const nx = normal.getX(i);
                const ny = normal.getY(i);
                const nz = normal.getZ(i);
                positions.setXYZ(i, ix - nx * d, iy - ny * d, iz - nz * d);
              }
              positions.needsUpdate = true;
              if (this.time >= 2) {
                this.time = -1;
                // this.mesh.material.vertexColors = true;
                // this.mesh.material.needsUpdate = true;
              }
            } else {
              const colors = this.mesh.geometry.attributes.color;
              const count = colors.count;
              for (let i = 0; i < count; i++) {
                colors.setXYZ(i, Math.random(), Math.random(), Math.random());
              }
              colors.needsUpdate = true;
            }
          }
        }
        loadModel(url) {
          return new Promise((resolve) => {
            if (!this.loader) {
              this.loader = new GLTFLoader();
            }
            this.loader.load(
              url,
              (obj) => {
                resolve(obj.scene);
              },

              function (xhr) {
                if (xhr.lengthComputable) {
                  const percentComplete = (xhr.loaded / xhr.total) * 100;
                  console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');
                }
              },
              function (error) {
                resolve(null);
                console.error(error);
              }
            );
          });
        }
        createChart(that) {
          this.loadModel('apple.glb').then((model) => {
            let obj = model.children[0].children[0];
            let geometry = obj.geometry;
            geometry.scale(2, 2, 2);
            geometry.center();
            const positions = geometry.attributes.position;
            geometry.setAttribute('initialPosition', positions.clone());
            const pos = positions.clone();
            const count = pos.count;
            const displacement = new Float32Array(count);

            for (let i = 0; i < count; i++) {
              displacement[i] = that.minDistance + that.distance * Math.random();
            }

            geometry.setAttribute('position', pos);

            geometry.setAttribute('displacement', new THREE.BufferAttribute(displacement, 1));
            geometry.attributes.position.setUsage(THREE.DynamicDrawUsage);

            let colors = [];

            for (let i = 0; i < positions.count; i++) {
              colors.push(Math.random(), Math.random(), Math.random());
            }
            geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));

            let material = new THREE.PointsMaterial({
              size: 1,
              color: new THREE.Color(that.color),
              vertexColors: true,
              transparent: true,
              depthTest: false
            });
            material.onBeforeCompile = (shader) => {
              console.log(shader);
              //修改片元着色器，使其变成发光圆点
              shader.fragmentShader = shader.fragmentShader.replace(
                `gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,
                circlePointsShader
              );
            };
            this.mesh = new THREE.Points(geometry, material);

            this.scene.add(this.mesh);
            this.setView(that.cameraPos, that.controlsPos);
          });
        }
      }

      var myApple = new MyApple();
      window.myApple = myApple;
      myApple.initThree(document.getElementById('canvas'));
      myApple.createChart({
        color: '#FF0000',
        distance: 10, //偏移距离
        minDistance: 5, //最小偏移距离,
        cameraPos: {
          x: 14.862527860505498,
          y: -7.19472939129663,
          z: 40.59051109739565
        },
        controlsPos: {
          x: 0,
          y: 0,
          z: 0
        }
      });
    </script>
  </body>
</html>
